#include "UdpCommunicator.h"
#include <QDebug>
#include <QMetaType>

UdpCommunicator::UdpCommunicator(QObject *parent)
    : QObject(parent),
      m_udpSocket(new QUdpSocket(this)),
      m_targetPort(0),
      m_receiveDebugEnabled(false),
      m_parseState(WaitingForHeader1),
      m_currentFunctionCode(static_cast<FunctionCode>(0)), // 初始化为0
      m_currentDataLength(0),
      m_currentCrcReceived(0)
{
    connect(m_udpSocket, &QUdpSocket::readyRead, this, &UdpCommunicator::readPendingDatagrams);

    // 注册所有需要通过信号槽传递的自定义结构体
    qRegisterMetaType<HeartbeatPacket>("HeartbeatPacket");
    qRegisterMetaType<DeviceInfoRequestPacket>("DeviceInfoRequestPacket");
    qRegisterMetaType<DeviceInfoResponsePacket>("DeviceInfoResponsePacket");
    qRegisterMetaType<ControlCommandPacket>("ControlCommandPacket");
    qRegisterMetaType<DataUploadPacket>("DataUploadPacket");
    qRegisterMetaType<FunctionCode>("FunctionCode"); // 注册FunctionCode枚举
}

UdpCommunicator::~UdpCommunicator()
{
    if (m_udpSocket->isOpen()) {
        m_udpSocket->close();
    }
}

bool UdpCommunicator::bindLocalPort(quint16 port)
{
    if (m_udpSocket->bind(QHostAddress::AnyIPv4, port)) {
        qDebug() << "UdpCommunicator: UDP socket bound to port:" << port;
        return true;
    } else {
        qWarning() << "UdpCommunicator: Failed to bind UDP socket to port:" << port << m_udpSocket->errorString();
        return false;
    }
}

void UdpCommunicator::setTargetAddress(const QHostAddress &address, quint16 port)
{
    m_targetAddress = address;
    m_targetPort = port;
    qDebug() << "UdpCommunicator: Target address set to:" << m_targetAddress.toString() << ":" << m_targetPort;
}

void UdpCommunicator::setTargetAddress(const QString &address, quint16 port)
{
    m_targetAddress = QHostAddress(address);
    m_targetPort = port;
    qDebug() << "UdpCommunicator: Target address set to:" << m_targetAddress.toString() << ":" << m_targetPort;
}

void UdpCommunicator::sendRawData(FunctionCode functionCode, const QByteArray &data)
{
    if (m_targetAddress.isNull() || m_targetPort == 0) {
        qWarning() << "UdpCommunicator: Target address or port not set. Cannot send data.";
        return;
    }

    QByteArray packet;
    QDataStream stream(&packet, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);

    // 包头
    stream << (quint8)0xAA << (quint8)0x55;
    // 功能码
    stream << static_cast<quint8>(functionCode); // 将枚举转为quint8
    // 数据长度
    stream << (quint16)data.length();
    // 数据
    packet.append(data);

    // 计算CRC16 (对功能码、数据长度和数据进行CRC校验)
    QByteArray crcData;
    QDataStream crcStream(&crcData, QIODevice::WriteOnly);
    crcStream.setByteOrder(QDataStream::BigEndian);
    crcStream << static_cast<quint8>(functionCode);
    crcStream << (quint16)data.length();
    crcData.append(data);

    quint16 crc = calculateCrc16(crcData);
    stream << crc; // 包尾 CRC16

    qint64 bytesSent = m_udpSocket->writeDatagram(packet, m_targetAddress, m_targetPort);
    if (bytesSent == -1) {
        qWarning() << "UdpCommunicator: Failed to send datagram:" << m_udpSocket->errorString();
    } else {
        qDebug() << "UdpCommunicator: Sent" << bytesSent << "bytes to" << m_targetAddress.toString() << ":" << m_targetPort
                 << "FuncCode:" << QString::number(functionCode, 16).toUpper()
                 << "Payload (hex):" << data.toHex();
        // qDebug() << "UdpCommunicator: Sent full packet (hex):" << packet.toHex(); // 完整包打印
    }
}

void UdpCommunicator::setReceiveDebugEnabled(bool enabled)
{
    m_receiveDebugEnabled = enabled;
    qDebug() << "UdpCommunicator: Receive debug printing" << (enabled ? "enabled" : "disabled");
}

void UdpCommunicator::readPendingDatagrams()
{
    while (m_udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(m_udpSocket->pendingDatagramSize());
        QHostAddress senderAddress;
        quint16 senderPort;

        m_udpSocket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort);

        if (m_receiveDebugEnabled) {
            UDP_RECEIVE_DEBUG(QString("Received datagram from %1:%2 Size: %3").arg(senderAddress.toString()).arg(senderPort).arg(datagram.size()));
            UDP_RECEIVE_DEBUG(QString("Received datagram (hex): %1").arg(datagram.toHex().constData()));
        }

        // 将当前数据包的发送方信息保存起来，以便在发出dataReceived信号时使用
        m_currentSenderAddress = senderAddress;
        m_currentSenderPort = senderPort;

        // 将接收到的数据添加到解析缓冲区
        m_receiveBuffer.append(datagram);

        // 逐字节解析
        while (!m_receiveBuffer.isEmpty()) {
            quint8 byte = (quint8)m_receiveBuffer.at(0);
            m_receiveBuffer.remove(0, 1); // 移除已处理的字节

            switch (m_parseState) {
            case WaitingForHeader1:
                if (byte == 0xAA) {
                    m_parseState = WaitingForHeader2;
                    m_currentData.clear(); // 清空上次的数据，准备接收新包
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG("State: WaitingForHeader1 -> WaitingForHeader2 (0xAA)");
                    }
                } else {
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG(QString("Resetting parse state: Expected 0xAA, got %1").arg(QString::number(byte, 16).toUpper()));
                    }
                }
                break;
            case WaitingForHeader2:
                if (byte == 0x55) {
                    m_parseState = WaitingForFunctionCode;
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG("State: WaitingForHeader2 -> WaitingForFunctionCode (0x55)");
                    }
                } else {
                    m_parseState = WaitingForHeader1;
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG(QString("Resetting parse state: Expected 0x55, got %1").arg(QString::number(byte, 16).toUpper()));
                    }
                }
                break;
            case WaitingForFunctionCode:
                m_currentFunctionCode = static_cast<FunctionCode>(byte); // 转换为枚举类型
                m_parseState = WaitingForDataLength1;
                if (m_receiveDebugEnabled) {
                    UDP_RECEIVE_DEBUG(QString("State: WaitingForFunctionCode -> WaitingForDataLength1 (FuncCode: %1)").arg(QString::number(m_currentFunctionCode, 16).toUpper()));
                }
                break;
            case WaitingForDataLength1:
                m_currentDataLength = (quint16)byte << 8; // 高位
                m_parseState = WaitingForDataLength2;
                if (m_receiveDebugEnabled) {
                    UDP_RECEIVE_DEBUG(QString("State: WaitingForDataLength1 (High byte: %1)").arg(QString::number(byte, 16).toUpper()));
                }
                break;
            case WaitingForDataLength2:
                m_currentDataLength |= byte; // 低位
                if (m_currentDataLength > 2048) { // 简单的数据长度校验，防止恶意包导致内存溢出, 适当增加一些
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG(QString("Received unusually large data length: %1. Resetting parse state.").arg(m_currentDataLength));
                    }
                    m_parseState = WaitingForHeader1;
                    break;
                }
                if (m_receiveDebugEnabled) {
                    UDP_RECEIVE_DEBUG(QString("State: WaitingForDataLength2 (Total Length: %1)").arg(m_currentDataLength));
                }
                if (m_currentDataLength == 0) {
                    m_parseState = WaitingForCrc1; // 没有数据，直接等CRC
                } else {
                    m_parseState = WaitingForData;
                }
                m_currentData.reserve(m_currentDataLength); // 预留数据空间
                break;
            case WaitingForData:
                m_currentData.append(byte);
                if (m_currentData.length() == m_currentDataLength) {
                    m_parseState = WaitingForCrc1;
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG("State: WaitingForData -> WaitingForCrc1 (Data complete)");
                    }
                }
                break;
            case WaitingForCrc1:
                m_currentCrcReceived = (quint16)byte << 8; // 高位
                m_parseState = WaitingForCrc2;
                if (m_receiveDebugEnabled) {
                    UDP_RECEIVE_DEBUG(QString("State: WaitingForCrc1 (High byte: %1)").arg(QString::number(byte, 16).toUpper()));
                }
                break;
            case WaitingForCrc2:
                m_currentCrcReceived |= byte; // 低位
                if (m_receiveDebugEnabled) {
                    UDP_RECEIVE_DEBUG(QString("State: WaitingForCrc2 (Total CRC: %1)").arg(QString::number(m_currentCrcReceived, 16).toUpper()));
                }

                // 此时一个完整的数据包已接收，进行CRC校验
                QByteArray crcCheckData;
                QDataStream crcCheckStream(&crcCheckData, QIODevice::WriteOnly);
                crcCheckStream.setByteOrder(QDataStream::LittleEndian);
                crcCheckStream << static_cast<quint8>(m_currentFunctionCode);
                crcCheckStream << m_currentDataLength;
                crcCheckData.append(m_currentData);

                if (checkCrc16(crcCheckData, m_currentCrcReceived)) {
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG("Data packet received and CRC verified!");
                    }
                    // 发出通用信号
                    emit dataReceived(m_currentFunctionCode, m_currentData,
                                      m_currentSenderAddress, m_currentSenderPort);

//                    // 根据功能码发出更具体的信号 (可选)
//                    processSpecificPacket(m_currentFunctionCode, m_currentData,
//                                          m_currentSenderAddress, m_currentSenderPort);

                } else {
                    if (m_receiveDebugEnabled) {
                        UDP_RECEIVE_DEBUG(QString("CRC check failed for received packet. Expected: %1 Received: %2")
                                          .arg(QString::number(calculateCrc16(crcCheckData), 16).toUpper())
                                          .arg(QString::number(m_currentCrcReceived, 16).toUpper()));
                    }
                }
                m_parseState = WaitingForHeader1; // 无论成功失败，都准备接收下一个包
                break;
            }
        }
    }
}

//// 辅助函数：根据功能码处理特定结构体（可以在这里解析并发出特定信号）
//void UdpCommunicator::processSpecificPacket(FunctionCode functionCode, const QByteArray &data,
//                                             const QHostAddress &senderAddress, quint16 senderPort)
//{
//    Q_UNUSED(senderAddress); // 如果特定信号不包含这些信息，可以忽略
//    Q_UNUSED(senderPort);

//    QDataStream stream(data);
//    stream.setByteOrder(QDataStream::BigEndian);

//    switch (functionCode) {
//    case FuncCode_Heartbeat:
//        if (data.size() == sizeof(HeartbeatPacket)) {
//            HeartbeatPacket packet;
//            stream.readRawData(reinterpret_cast<char*>(&packet), sizeof(HeartbeatPacket));
//            emit heartbeatReceived(packet, senderAddress, senderPort);
//        } else {
//            qWarning() << "UdpCommunicator: Received HeartbeatPacket with incorrect size:" << data.size() << "Expected:" << sizeof(HeartbeatPacket);
//        }
//        break;
//    case FuncCode_DeviceInfoResponse:
//        if (data.size() == sizeof(DeviceInfoResponsePacket)) {
//            DeviceInfoResponsePacket packet;
//            stream.readRawData(reinterpret_cast<char*>(&packet), sizeof(DeviceInfoResponsePacket));
//            emit deviceInfoResponseReceived(packet, senderAddress, senderPort);
//        } else {
//            qWarning() << "UdpCommunicator: Received DeviceInfoResponsePacket with incorrect size:" << data.size() << "Expected:" << sizeof(DeviceInfoResponsePacket);
//        }
//        break;
//    // ... 处理其他功能码的结构体解析和信号发出
//    default:
//        // 其他功能码，或者未知功能码，由dataReceived通用信号处理
//        break;
//    }
//}


// CRC16-CCITT (XMODEM) 实现
quint16 UdpCommunicator::calculateCrc16(const QByteArray &data)
{
    quint16 crc = 0x0000;
    quint16 polynomial = 0x1021;

    for (char byteValue : data) {
        quint8 byte = (quint8)byteValue;
        crc ^= (quint16)(byte << 8);

        for (int i = 0; i < 8; ++i) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ polynomial;
            } else {
                crc <<= 1;
            }
        }
    }
    return crc;
}

bool UdpCommunicator::checkCrc16(const QByteArray &data, quint16 crc)
{
    return calculateCrc16(data) == crc;
}
